﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using ZeroBug.EasyFlow.Core;

namespace EasyFlow
{
    public partial class StepViewModel : ObservableObject
    {
        Step _step;
        [ObservableProperty]
        string _description;
        [ObservableProperty]
        double _depth;
        [ObservableProperty]
        string _icon;
        [ObservableProperty]
        bool _isRunning;
        [ObservableProperty]
        ObservableCollection<StepViewModel> _children;
        [ObservableProperty]
        DateTime _startTime;
        [ObservableProperty]
        DateTime _endTime;
        [ObservableProperty]
        double _stepTime;
        [ObservableProperty]
        bool _prepare2Run;
        [ObservableProperty]
        bool _isErr;
        [ObservableProperty]
        bool _isCompileErr;
        [ObservableProperty]
        bool _isChildrenExpanded;
        [ObservableProperty]
        StepStatus _status;
        private string _tip;
        public string Tip
        {
            get => _step.GetOperator().GetTip(_step);
            set => SetProperty(ref _tip, value);
        }
        private ObservableCollection<VariableExpressionViewModel> _parameters;
        public ObservableCollection<VariableExpressionViewModel> Parameters
        {
            get => new ObservableCollection<VariableExpressionViewModel>(_step.Parameters.Values.Select(v => new VariableExpressionViewModel(v)));
            set => SetProperty(ref _parameters, value);
        }
        private ObservableCollection<VariableJudgeViewModel> _conditions;
        public ObservableCollection<VariableJudgeViewModel> Conditions
        {
            get => new ObservableCollection<VariableJudgeViewModel>(_step.Conditions.Select(c => new VariableJudgeViewModel(c)));
            set => SetProperty(ref _conditions, value);
        }

        public StepViewModel Parent { get; set; }
        public StepViewModel(Step step, double depth = 0)
        {
            this._step = step;
            this._description = step.Description;
            if(!string.IsNullOrEmpty(step.Alias))
                this._description = step.Alias;
            Depth = depth;
            Icon = step.GetOperator().Icon;
            Prepare2Run = step.Prepare2Run;
            step.OnStepPrepare2Run += stepPrepare;
            step.OnStepBeginNewCycle += stepNewCylcle;
            step.OnStepStart += stepStart;
            step.OnStepFinish += stepFinish;
            step.OnStepErr += stepErr;
            step.OnCompileFinish += stepCompileFinish;
            this.IsChildrenExpanded = step.IsExpanded;
            Children = new ObservableCollection<StepViewModel>();
            if(step.Children != null && step.Children.Count > 0)
                depth++;
            foreach (var item in step.Children)
            {
                StepViewModel newStepVM = null;
                if (item.IsConditionNode)
                    newStepVM = new ConditionNodeStepViewModel(item, depth);
                else
                    newStepVM = new StepViewModel(item, depth);
                newStepVM.Parent = this;
                newStepVM.IsChildrenExpanded = item.IsExpanded;
                Children.Add(newStepVM);
            }
        }

        private void stepNewCylcle()
        {
            Status = StepStatus.Wait;
        }

        public void AddChildren(StepViewModel child, bool isInsert = false, int insertIndex = 0)
        {
            child.Depth = this.Depth + 1;
            child.Parent = this;
            if (isInsert)
                Children.Insert(insertIndex, child);
            else
                Children.Add(child);
        }
        public Step GetStep() => _step;
        public void stepPrepare()
        {
            Prepare2Run = true;
        }
        private void stepStart(DateTime startTime)
        {
            IsErr = false;
            StartTime = startTime;
            Prepare2Run = false;
            IsRunning = true;
            Status = StepStatus.Running;
        }
        private void stepFinish(DateTime endTime)
        {
            EndTime = endTime;
            StepTime = (EndTime - StartTime).TotalMilliseconds;
            IsRunning = false;
            Status = StepStatus.Finish;
        }
        private void stepErr(DateTime errTime, string errInfo)
        {
            IsErr = true;
            Status = StepStatus.Error;
        }
        private void stepCompileFinish(bool isSuccess, string errInfo)
        {
            IsCompileErr = !isSuccess;
            if (IsCompileErr)
                Status = StepStatus.Alert;
            //else
            //    Status = StepStatus.Wait;
        }
        public void ResetViewModel()
        {
            this.IsRunning = false;
            this.Prepare2Run = false;
            this.IsCompileErr = false;
            if (this.Children != null && this.Children.Count > 0)
            {
                foreach (var child in this.Children)
                {
                    child.ResetViewModel();
                }
            }
        }
        partial void OnIsChildrenExpandedChanged(bool oldValue, bool newValue)
        {
            this._step.IsExpanded = newValue;
        }
        partial void OnDescriptionChanged(string? oldValue, string newValue)
        {
            this._step.Alias = newValue;
        }
    }
    public enum StepStatus
    {
        Wait,
        Running,
        Finish,
        Info,
        Error,
        Alert,
    }
}
